﻿#include "C3fdPdfReport.h"

#include <QApplication>
#include <QScreen>
#include <QPainter>
#include <QDebug>
#include "Common/C3fdProject.h"
#include "Common/C3fdCase.h"
#include "Common/C3fdReportData.h"


namespace MainWidget
{

	C3fdPdfReport::C3fdPdfReport(QString fileName)
		: m_PdfFile(fileName)
	{
		if (m_PdfWriter == nullptr)
		{
			m_PdfWriter = new QPdfWriter(m_PdfFile);
		}
		m_PdfWriter->setPageSize(QPdfWriter::A4);
		m_PdfWriter->setPageMargins(QMargins(0, 0, 0, 0));
		m_PdfWriter->setResolution(96 * getDpi());
		m_PdfWriter->setCreator("FastCAE");
		m_PdfWriter->setPageMargins(QMarginsF(30, 30, 30, 30));
		m_PdfWriter->setPageOrientation(QPageLayout::Portrait);
		m_PdfWriter->setPdfVersion(QPagedPaintDevice::PdfVersion_1_6);
		m_PdfWriter->setTitle("C3FD");
	}

	C3fdPdfReport::~C3fdPdfReport()
	{
		if (m_PdfWriter != nullptr)
		{
			delete m_PdfWriter;
			m_PdfWriter = nullptr;
		}
	}

	void C3fdPdfReport::generate()
	{

		auto* currentCase = Common::C3fdProject::instance()->getCurrentCase();
		if (currentCase == nullptr) {
			return;
		}
		auto* reportData = currentCase->getReportData();
		if (reportData == nullptr) {
			return;
		}
		QPainter painter(m_PdfWriter);
		painter.setRenderHint(QPainter::Antialiasing);

		QFont font;
		font.setFamily("SimSun");
		font.setPixelSize(30);
		painter.setFont(font);
		painter.setPen(Qt::black);

		/************** 标题 *****************/
		int currentY = 60;
		painter.drawText(0, currentY, m_PdfWriter->width(), 30, Qt::AlignHCenter | Qt::AlignCenter, tr("XXX 3D calculation result report"));
		currentY += 20;

		auto meshModel = reportData->getMeshModel();

		/************** 网格模型 *****************/
		currentY += 40;
		font.setPixelSize(12);
		painter.setFont(font);
		painter.drawText(0, currentY, tr("1 Calculation grid model settings"));
		currentY += 20;

		// 图片和表格的题注序号
		int tableIndex = 0, imageIndex = 0;

		painter.drawText(0, currentY, m_PdfWriter->width(), 20, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Table %1 Grid parameter settings")).arg(++tableIndex));
		currentY += 20;

		int tdWidth = 80, tdHeight = 20;
		int pointLTX = (m_PdfWriter->width() - tdWidth * 4) / 2;
		painter.drawRect(pointLTX, currentY, tdWidth, tdHeight);
		painter.drawText(pointLTX, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Blade Row"));
		painter.drawRect(pointLTX + tdWidth, currentY, tdWidth, tdHeight);
		painter.drawText(pointLTX + tdWidth, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Blade Num"));
		painter.drawRect(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight);
		painter.drawText(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Gap(mm)"));
		painter.drawRect(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight);
		painter.drawText(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Mesh Num"));
		currentY += tdHeight;

		int totalNumOfMesh = 0;
		for (int i = 0; i < meshModel.size(); i++)
		{
			totalNumOfMesh += meshModel.at(i).numOfMesh;
			painter.drawRect(pointLTX, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, meshModel.at(i).name);
			painter.drawRect(pointLTX + tdWidth, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX + tdWidth, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString("%1").arg(meshModel.at(i).numOfBlade));
			painter.drawRect(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString("%1").arg(meshModel.at(i).gap));
			painter.drawRect(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString("%1").arg(meshModel.at(i).numOfMesh));
			currentY += tdHeight;
		}
		painter.drawRect(pointLTX, currentY, tdWidth * 4, tdHeight);
		painter.drawText(pointLTX, currentY, tdWidth * 4, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Total Mesh Num %1")).arg(totalNumOfMesh));
		currentY += tdHeight;

		/************** 边界模型 *****************/
		auto boundaryModel = reportData->getBoundaryModel();
		currentY += 40;
		painter.drawText(0, currentY, tr("2 Calculation boundary model settings"));
		currentY += 20;
		painter.drawText(0, currentY, m_PdfWriter->width(), 20, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Table %1 Calculation Boundary Condition Setting")).arg(++tableIndex));
		currentY += 20;

		int tdWidth1 = 80, tdWidth2 = 160;
		pointLTX = (m_PdfWriter->width() - tdWidth1 - tdWidth2) / 2;

		painter.drawRect(pointLTX, currentY, tdWidth1, tdHeight * 2);
		painter.drawText(pointLTX, currentY, tdWidth1, tdHeight * 2, Qt::AlignHCenter | Qt::AlignCenter, tr("Inlet"));
		painter.drawRect(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight);
		painter.drawText(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Total Pressure: %1 Pa")).arg(boundaryModel.inletPressure));
		currentY += tdHeight;

		painter.drawRect(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight);
		painter.drawText(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Total Temperature: %1 K")).arg(boundaryModel.inletPressure));
		currentY += tdHeight;

		painter.drawRect(pointLTX, currentY, tdWidth1, tdHeight);
		painter.drawText(pointLTX, currentY, tdWidth1, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Outlet"));
		painter.drawRect(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight);
		// 背压随工况会变，所以不写具体值，只写"平均背压"
		//painter.drawText(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Average back pressure: %1 Pa")).arg(boundaryModel.outletPressure));
		painter.drawText(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Average back pressure")).arg(boundaryModel.outletPressure));
		currentY += tdHeight;

		painter.drawRect(pointLTX, currentY, tdWidth1, tdHeight);
		painter.drawText(pointLTX, currentY, tdWidth1, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Rotation Speed"));
		painter.drawRect(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight);
		painter.drawText(pointLTX + tdWidth1, currentY, tdWidth2, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("%1 RPM")).arg(boundaryModel.rotationSpeed));
		currentY += tdHeight;

		/************** 性能数据 *****************/
		auto performanceDatas = reportData->getPerformanceDatas();
		currentY += 40;
		painter.drawText(0, currentY, tr("3 Calculate performance data"));

		for (auto performData : performanceDatas) {

			int totalRow = performData.datas.size();

			if (totalRow * tdHeight + 60 + currentY > m_PdfWriter->height()) {
				m_PdfWriter->newPage();
				currentY = 0;
			}
			currentY += 20;
			painter.drawText(0, currentY, m_PdfWriter->width(), 20, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Table %1 %2").arg(++tableIndex).arg(performData.name)));
			currentY += 20;

			tdWidth = 100;
			pointLTX = (m_PdfWriter->width() - tdWidth * 4) / 2;

			painter.drawRect(pointLTX, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Rotation Speed(RPM)"));
			painter.drawRect(pointLTX + tdWidth, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX + tdWidth, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Inlet Flow(Kg/s)"));
			painter.drawRect(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Pressure Ratio"));
			painter.drawRect(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight);
			painter.drawText(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, tr("Efficiency"));
			currentY += tdHeight;
			// 合并单元格
			painter.drawRect(pointLTX, currentY, tdWidth, tdHeight * totalRow);
			painter.drawText(pointLTX, currentY, tdWidth, tdHeight * totalRow, Qt::AlignHCenter | Qt::AlignCenter, QString("%1").arg(performData.rotationSpeed));
			for (int i = 0; i < totalRow; i++)
			{
				painter.drawRect(pointLTX + tdWidth, currentY, tdWidth, tdHeight);
				painter.drawText(pointLTX + tdWidth, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString("%1").arg(performData.datas.at(i).inletFlow));
				painter.drawRect(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight);
				painter.drawText(pointLTX + tdWidth * 2, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString("%1").arg(performData.datas.at(i).pressureRatio));
				painter.drawRect(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight);
				painter.drawText(pointLTX + tdWidth * 3, currentY, tdWidth, tdHeight, Qt::AlignHCenter | Qt::AlignCenter, QString("%1").arg(performData.datas.at(i).efficiency));
				currentY += tdHeight;
			}
		}


		/************** 性能图 *****************/
		auto perfotmanceImages = reportData->getPerformanceImages();
		if (60 + currentY > m_PdfWriter->height()) {
			m_PdfWriter->newPage();
			currentY = 0;
		}
		else {
			currentY += 40;
		}
		painter.drawText(0, currentY, tr("4 Performance Diagram"));
		currentY += 20;

#ifdef false

		for (auto performImage : perfotmanceImages) {

			int numOfImage = performImage.imgs.size();
			int numOfEachRow = numOfImage > 3 ? 2 : numOfImage;

			int targetImgWidth = m_PdfWriter->width()* 0.8 / numOfEachRow;
			targetImgWidth = targetImgWidth > 280 ? 280 : targetImgWidth;
			int targetImgHeight = targetImgWidth;
			int targetImgX = m_PdfWriter->width() / 2 * 0.2;

			for (int i = 0; i < numOfImage; i++)
			{
				QPixmap img(performImage.imgs.at(i));
				QPixmap targetImg = img.scaledToWidth(targetImgWidth);
				targetImgHeight = targetImg.height();
				if (i % numOfEachRow == 0) {
					if (targetImgHeight + 20 + currentY > m_PdfWriter->height()) {
						m_PdfWriter->newPage();
						currentY = 0;
					}
					else {
						currentY += 20;
					}
				}
				painter.drawPixmap(
					QRect(targetImgX + (i%numOfEachRow)*(targetImgWidth + 10), currentY, targetImgWidth, targetImgHeight),
					targetImg,
					QRect(0, 0, targetImgWidth, targetImgHeight));
				if (i % numOfEachRow + 1 == numOfEachRow) {
					currentY += targetImgHeight;
				}
			}
			painter.drawText(0, currentY, m_PdfWriter->width(), 20, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Figure %1 %2")).arg(++imageIndex).arg(performImage.name));
			currentY += 20;
	}

#else
		{
			int numOfImage = perfotmanceImages.size();
			int numOfEachRow = numOfImage > 3 ? 2 : numOfImage;

			int targetImgWidth = m_PdfWriter->width()* 0.8 / numOfEachRow;
			targetImgWidth = targetImgWidth > 280 ? 280 : targetImgWidth;
			int targetImgHeight = targetImgWidth;
			int targetImgX = m_PdfWriter->width() / 2 * 0.2;

			for (int i = 0; i < numOfImage; ++i) {
				auto performImage = perfotmanceImages.at(i);


				QPixmap img(performImage.img);
				QPixmap targetImg = img.scaledToWidth(targetImgWidth);
				targetImgHeight = targetImg.height();
				if (i % numOfEachRow == 0) {
					if (targetImgHeight + 20 + currentY > m_PdfWriter->height()) {
						m_PdfWriter->newPage();
						currentY = 0;
					}
					else {
						currentY += 20;
					}
				}
				painter.drawPixmap(
					QRect(targetImgX + (i%numOfEachRow)*(targetImgWidth + 10), currentY, targetImgWidth, targetImgHeight),
					targetImg,
					QRect(0, 0, targetImgWidth, targetImgHeight));
				painter.drawText(targetImgX + (i%numOfEachRow)*(targetImgWidth + 10), currentY + targetImgHeight + 20, targetImgWidth, 20, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Figure %1 %2")).arg(++imageIndex).arg(performImage.name));

				if (i % numOfEachRow + 1 == numOfEachRow) {
					currentY += (targetImgHeight + 20);
				}
			}
		}
#endif // false


		/************** 流场分析 *****************/
#if false
		auto flowImages = reportData->getFlowImages();
		if (60 + currentY > m_PdfWriter->height()) {
			m_PdfWriter->newPage();
			currentY = 0;
		}
		else {
			currentY += 40;
		}
		painter.drawText(0, currentY, tr("5 Flow field analysis"));
		currentY += 20;

		int i = 0;
		auto targetImgWidth = m_PdfWriter->width() * 0.8 / 2;
		auto targetImgHeight = targetImgWidth;
		auto targetImgX = m_PdfWriter->width() * 0.2 / 2;
		for (auto flowImg : flowImages) {

			QPixmap img(flowImg.img);
			img = img.scaledToWidth(targetImgWidth);
			targetImgHeight = img.height();
			if (img.height() + 20 + currentY > m_PdfWriter->height()) {
				m_PdfWriter->newPage();
				currentY = 0;
			}

			painter.drawPixmap(
				QRect(targetImgX + (i % 2)*(targetImgWidth + 10), currentY, targetImgWidth, targetImgHeight),
				img,
				QRect(0, 0, targetImgWidth, targetImgHeight));
			painter.drawText(targetImgX + (i % 2)*targetImgWidth, currentY + targetImgHeight, targetImgWidth, 20, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Figure %1 %2")).arg(++imageIndex).arg(flowImg.name));
			if (i % 2 == 1) {
				currentY += (targetImgHeight + 20);
			}
			++i;
}
#else
		auto flowImages = reportData->getFlowImages();
		if (60 + currentY > m_PdfWriter->height()) {
			m_PdfWriter->newPage();
			currentY = 0;
		}
		else {
			currentY += 40;
		}
		painter.drawText(0, currentY, tr("5 Flow field analysis"));
		currentY += 20;

		auto targetImgWidth = m_PdfWriter->width() * 0.8;
		auto targetImgHeight = targetImgWidth;
		auto targetImgX = m_PdfWriter->width() * 0.2 / 2;
		for (auto flowImg : flowImages) {

			QPixmap img(flowImg.img);
			img = img.scaledToWidth(targetImgWidth);
			targetImgHeight = img.height();
			if (img.height() + 20 + currentY > m_PdfWriter->height()) {
				m_PdfWriter->newPage();
				currentY = 0;
			}

			painter.drawPixmap(
				QRect(targetImgX, currentY, targetImgWidth, targetImgHeight),
				img,
				QRect(0, 0, targetImgWidth, targetImgHeight));
			currentY += targetImgHeight;
			painter.drawText(targetImgX, currentY, targetImgWidth, 20, Qt::AlignHCenter | Qt::AlignCenter, QString(tr("Figure %1 %2")).arg(++imageIndex).arg(flowImg.name));
			currentY += 20;
		}
#endif
}

	qreal C3fdPdfReport::getDpi()
	{
		return QApplication::primaryScreen()->devicePixelRatio();
	}

}